package ua.edu.nuos.jeetraining2012.cms.entity;

import ua.edu.nuos.jeetraining2012.cms.dto.predefined.StandardUserStatuses;

import javax.persistence.*;
import javax.validation.constraints.NotNull;
import java.io.Serializable;
import java.util.Date;

/**
 * Class, that describes relation between Students and courses.
 * <p/>
 * Additional field is join_date with value of date, when student became to course.<br/>
 * Current student "enrollment" status, i.g.: pending (awaiting for instructor confirmation) or enrolled
 * (student approved to be enrolled to course)<br/>
 * Enroll
 *
 * @author Victor N. Ganichev victor.ganichev@gmail.com
 * @version 1.0 Date: 16.05.13 Time: 18:54
 * @since 1.0
 */
@Entity
@Table(name = "users_to_courses")
@IdClass(UsersToCourseId.class)
public class UsersToCourseEntity implements Serializable {

    /**
     * Course ID.
     */
    @Id
    @ManyToOne(optional = false)
    @JoinColumn(name = "course_id")
    @NotNull
    private CourseEntity courseId;

    /**
     * Student ID.
     */
    @Id
    @ManyToOne(optional = false)
    @JoinColumn(name = "user_id")
    @NotNull
    private UserEntity userId;

    /**
     * Student join date.
     */
    @Column(name = "join_date",nullable = false)
    @Basic(optional = false)
    @Temporal(TemporalType.TIMESTAMP)
    private Date joinDate;

    /**
     * Define enroll status.
     * Possible statuses are:
     * <ul>
     *     <li>
     *         {@link ua.edu.nuos.jeetraining2012.cms.dto.predefined.StandardUserStatuses#ENROLLED} &mdash;
     *         for enrolled users.
     *     </li>
     *     <li>
     *         {@link ua.edu.nuos.jeetraining2012.cms.dto.predefined.StandardUserStatuses#PENDING} &mdash;
     *         for students, that are awaiting for instructor confirmation.
     *     </li>
     * </ul>
     */
    @Column(name = "student_status", nullable = false, columnDefinition = "VARCHAR(10) DEFAULT 'pending'")
    @Basic(optional = true)
    private String status;

    /** Define instructor id, who had approved students enrollment. */
    @Column(name = "approved_by", nullable = true)
    @Basic(optional = true)
    private Long approvedByInstructorId;

    /** Define approve date. */
    @Column(name = "approve_date", nullable = true)
    @Basic(optional = true)
    @Temporal(TemporalType.TIMESTAMP)
    private Date approveDate;

    /** Define user's svn link. */
    @Column(name="svn_link", nullable=true)
    @Basic(optional = true)
    private String svnLink;


    // Default constructor
    public UsersToCourseEntity() {}

    // Getters & Setters
    public CourseEntity getCourseId() {
        return courseId;
    }

    public void setCourseId(CourseEntity courseId) {
        this.courseId = courseId;
    }

    public UserEntity getUserId() {
        return userId;
    }

    public void setUserId(UserEntity userId) {
        this.userId = userId;
    }

    public Date getJoinDate() {
        return joinDate;
    }

    public void setJoinDate(Date joinDate) {
        this.joinDate = joinDate;
    }

    public String getStatus() {
        return status;
    }

    public void setStatus(String status) {
        this.status = status;
    }

    public Long getApprovedByInstructorId() {
        return approvedByInstructorId;
    }

    public void setApprovedByInstructorId(Long approvedByInstructorId) {
        this.approvedByInstructorId = approvedByInstructorId;
    }

    public Date getApproveDate() {
        return approveDate;
    }

    public void setApproveDate(Date approveDate) {
        this.approveDate = approveDate;
    }

    @PrePersist
    public void prePersist() {
        this.joinDate = new Date();
        this.status = StandardUserStatuses.PENDING;
    }

    public String getSvnLink() {
        return svnLink;
    }

    public void setSvnLink(String svnLink) {
        this.svnLink = svnLink;
    }

    // Overrides
    @Override
    public boolean equals(Object o) {
        if (this == o) return true;
        if (o == null || getClass() != o.getClass()) return false;

        UsersToCourseEntity entity = (UsersToCourseEntity) o;

        if (courseId != null ? !courseId.equals(entity.courseId) : entity.courseId != null) return false;
        if (userId != null ? !userId.equals(entity.userId) : entity.userId != null) return false;

        return true;
    }

    @Override
    public int hashCode() {
        int result = courseId != null ? courseId.hashCode() : 0;
        result = 31 * result + (userId != null ? userId.hashCode() : 0);
        return result;
    }

    @Override
    public String toString() {
        return "UsersToCourseEntity{" +
                "courseId=" + courseId +
                ", userId=" + userId +
                ", joinDate=" + joinDate +
                ", status='" + status + '\'' +
                ", approvedByInstructorId=" + approvedByInstructorId +
                ", approveDate=" + approveDate +
                '}';
    }
}
